﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace Lightray.Hattrick.ChppLib.EntityTypes
{
    public class YouthPlayer : BasicPlayer
    {
        private Skill[] _unlockedSkills;
        private Skill[] _unlockedPotentialSkills;

        #region Properties
        public DateTime ArrivalDate { get; private set; }
        public TimeSpan CanBePromotedTime { get; private set; }
        public bool CanBePromoted { get { return CanBePromotedTime.Days <= 0; } }
        public bool HasUnlockedSkills { get { return _unlockedPotentialSkills.Length > 0 || _unlockedSkills.Length > 0; } }

        public SkillLevel KeeperPotential { get; private set; }
        public SkillLevel PlaymakingPotential { get; private set; }
        public SkillLevel ScoringPotential { get; private set; }
        public SkillLevel PassingPotential { get; private set; }
        public SkillLevel WingerPotential { get; private set; }
        public SkillLevel DefendingPotential { get; private set; }
        public SkillLevel SetPiecesPotential { get; private set; }

        public Team SeniorTeam { get; private set; }
        protected internal int SeniorTeamID { get; protected set; }
        #endregion

        public bool ReachedPotential(Skill skill)
        {
            return GetSkillLevel(skill) == GetPotentialSkillLevel(skill);
        }

        public SkillLevel GetPotentialSkillLevel(Skill skill)
        {
            switch (skill)
            {
                case Skill.Keeper:
                    return KeeperPotential;
                case Skill.Playmaking:
                    return PlaymakingPotential;
                case Skill.Scoring:
                    return ScoringPotential;
                case Skill.Passing:
                    return PassingPotential;
                case Skill.Winger:
                    return WingerPotential;
                case Skill.Defending:
                    return DefendingPotential;
                case Skill.SetPieces:
                    return SetPiecesPotential;
            }
            return SkillLevel.NonExistent;
        }

        public bool SkillUnlocked(Skill skill)
        {
            return _unlockedSkills.Contains(skill);
        }

        public bool PotentialSkillUnlocked(Skill skill)
        {
            return _unlockedPotentialSkills.Contains(skill);
        }        
        
        protected YouthPlayer() { }

        public static EntityCollection<YouthPlayer> FromXml(XDocument youthPlayerListXml)
        {
            HattrickXmlReader reader = new HattrickXmlReader(youthPlayerListXml);
            DateTime dataTime = reader.ReadDate("FetchedDate");
            int teamId = reader.ReadNumber("YouthTeamID");
            int seniorTeamId = reader.ReadNumber("SeniorTeamID");

            List<YouthPlayer> ret = new List<YouthPlayer>();
            foreach (var player in youthPlayerListXml.Descendants("YouthPlayer"))
                ret.Add(YouthPlayer.fromPlayerNode(player, teamId, seniorTeamId, dataTime));

            return ret.ToEntityCollection();
        }
        
        private static YouthPlayer fromPlayerNode(XElement playerNode, int teamId, int seniorTeamId, DateTime dataTime)
        {
            HattrickXmlReader reader = new HattrickXmlReader(playerNode);
            return new YouthPlayer()
            {
                // TODO: change to consts
                ID = reader.ReadNumber("YouthPlayerID"),
                DataTime = dataTime,
                Age = reader.ReadHattrickAge("Age", "AgeDays"),
                FirstName = reader.ReadString("FirstName"),
                LastName = reader.ReadString("LastName"),
                ArrivalDate = reader.ReadDate("ArrivalDate"),
                CanBePromotedTime = TimeSpan.FromDays(reader.ReadNumber("CanBePromotedIn")),
                Cards = reader.ReadNumberOrDefault("Cards", -2),
                InjuryLevel = reader.ReadNumberOrDefault("InjuryLevel", -1),
                Specialty = reader.ReadSpecialty("Specialty"),
                CareerGoals = reader.ReadNumberOrDefault("CareerGoals", 0),
                CareerHattricks = reader.ReadNumberOrDefault("CareerHattricks", 0),
                LeagueGoals = reader.ReadNumberOrDefault("LeagueGoals", 0),                                                
                Keeper = reader.ReadSkill("KeeperSkill"),
                KeeperPotential = reader.ReadSkill("KeeperSkillMax"),
                Defending = reader.ReadSkill("DefenderSkill"),
                DefendingPotential = reader.ReadSkill("DefenderSkillMax"),
                Playmaking = reader.ReadSkill("PlaymakerSkill"),
                PlaymakingPotential = reader.ReadSkill("PlaymakerSkillMax"),
                Winger = reader.ReadSkill("WingerSkill"),
                WingerPotential = reader.ReadSkill("WingerSkillMax"),
                Passing = reader.ReadSkill("PassingSkill"),
                PassingPotential = reader.ReadSkill("PassingSkillMax"),
                Scoring = reader.ReadSkill("ScorerSkill"),
                ScoringPotential = reader.ReadSkill("ScorerSkillMax"),
                SetPieces = reader.ReadSkill("SetPiecesSkill"),
                SetPiecesPotential = reader.ReadSkill("SetPiecesSkillMax"),

                _unlockedSkills = readUnlockedSkills(reader, 
                                                     "KeeperSkill", 
                                                     "DefenderSkill",
                                                     "PlaymakerSkill",
                                                     "WingerSkill", 
                                                     "PassingSkill",
                                                     "ScorerSkill", 
                                                     "SetPiecesSkill" ),
                _unlockedPotentialSkills = readUnlockedSkills(reader,
                                                              "KeeperSkillMax",
                                                              "DefenderSkillMax", 
                                                              "PlaymakerSkillMax", 
                                                              "WingerSkillMax", 
                                                              "PassingSkillMax", 
                                                              "ScorerSkillMax",
                                                              "SetPiecesSkillMax"),
                                
                LastMatch = PlayerMatchStats.FromXml(reader.ReadElement("LastMatch")),

                TeamID = teamId,
                SeniorTeamID = seniorTeamId,
            };
        }

        private static Skill[] readUnlockedSkills(HattrickXmlReader reader, params string[] skills)
        {
            List<Skill> ret = new List<Skill>();
            foreach (string elementName in skills)
                if (reader.ReadAttributeBoolean(elementName, "MayUnlock"))
                    ret.Add(skillElementNameToSkill(elementName));

            return ret.ToArray();
        }

        private static Skill skillElementNameToSkill(string elementName)
        {
            if (elementName.StartsWith("Keeper"))
                return Skill.Keeper;
            else if (elementName.StartsWith("Defender"))
                return Skill.Defending;
            else if (elementName.StartsWith("Playmaker"))
                return Skill.Playmaking;
            else if (elementName.StartsWith("Winger"))
                return Skill.Winger;
            else if (elementName.StartsWith("Passing"))
                return Skill.Passing;
            else if (elementName.StartsWith("Scorer"))
                return Skill.Scoring;
            else if (elementName.StartsWith("SetPieces"))
                return Skill.SetPieces;

            throw new Exception("Invalid element name");
        }
    }
}
